/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.Comandos;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Expressoes.RegraExpressao;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;

import java.util.LinkedList;

/**
 *
 * @author Ivo Romário
 */
public class RegraPrintf extends Regra {

    protected static Regra instancia;

    protected String estrutura = "printf '(' charconst {',' <expressao>} ')' ';'";

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraPrintf(){

    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraPrintf getInstance() {
        if (instancia == null) {
            instancia = new RegraPrintf();
        }
        return (RegraPrintf) instancia;
    }
    

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

         ErroSintaticoException erros = new ErroSintaticoException();

         NoArvore naoTerminalPrintf = new NoArvore("<printf>", false);

         naoTerminalPrintf.adicionaFilho(reconhecerPrintf(listaTokens));

         try{
            naoTerminalPrintf.adicionaFilho(reconheceLexema(listaTokens, "delimitador", "(",estrutura));
         }
         catch(ErroSintaticoException e){
         }

         try{
             naoTerminalPrintf.adicionaFilho(reconheceToken(listaTokens, "charconst",estrutura));
         }
         catch(ErroSintaticoException e){
         }

         try{
             while (listaTokens.getFirst().getToken().equals("delimitador") && listaTokens.getFirst().getLexema().equals(",")){
                naoTerminalPrintf.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ",",estrutura));
                naoTerminalPrintf.adicionaFilho(RegraExpressao.getInstance().analisar(listaTokens));
             }
         }
         catch(ErroSintaticoException e){
         }

         try{
             naoTerminalPrintf.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ")",estrutura));
         }
         catch(ErroSintaticoException e){
                while (e.size() != 0) {
                erros.addErros(e.getErros());
            }
         }

         try{
             naoTerminalPrintf.adicionaFilho(reconheceLexema(listaTokens, "delimitador", listaTokens.getFirst().getLexema(),estrutura));
         }
         catch(ErroSintaticoException e){
                while (e.size() != 0) {
                erros.addErros(e.getErros());
            }
         }

        if(erros.size() != 0){
            throw erros;
        }
         
         return naoTerminalPrintf;

    }

    public NoArvore reconhecerPrintf (LinkedList<LinkToken> listaTokens){

            listaTokens.removeFirst();
            return new NoArvore("printf", true);
    }

   
    @Override
    protected void setPrimeiro() {
        this.primeiro.add("printf");
    }

    @Override
    protected void setSeguinte() {
        seguinte = RegraCmd.getInstance().getSeguinte();
    }

}
